
// === uuMeta.bond ===
// depend: uuMeta, uuMeta.uniqueid
/*
uuMeta.bond(node, key, value)
uuMeta.unbond(node, key = "")
uuMeta.bond.get(node, key) - return value
uuMeta.bond.keys(node) - return ["key", ...]
uuMeta.bond.nodes(key) - return [node, ...]
 */
(function uuMetaBondScope() {
var _mm = uuMeta,
    _uiddb = {}, // { uid: node, ... }
    _keydb = {}, // { key: {uid: 1, ...}, ... }
    _BOND = "uubond";

// uuMeta.bond - bond key,value pair for element
function bond(node,    // @param Node:
              key,     // @param String: keyword
              value) { // @param Mix: value
                       // @return Mix: value
  var uid = _mm.uid(node);

  !(_BOND in node) && (node[_BOND] = {});
  node[_BOND][key] = value;

  !(uid in _uiddb) && (_uiddb[uid] = node);
  !(key in _keydb) && (_keydb[key] = {});
  _keydb[key][uid] = 1;
}

// uuMeta.unbond
function unbond(node,  // @param Node:
                key) { // @param String(= ""): keyword
                       //        "" is unbond all keywords
  var uid = _mm.uid(node), i = 0, ary;

  if (_BOND in node) {
    key ? (delete node[_BOND][key])
        : (delete node[_BOND]); // all
  }
  ary = key ? [key] : keys(node);
  while ( (key = ary[i++]) ) {
    if (uid in _keydb[key]) {
      delete _keydb[key][uid];
    }
  }
}

// uuMeta.bond.get - get bonded data
function get(node,  // @param Node:
             key) { // @param String: keyword
                    // @return Mix/undefined: bonded value
  return (_BOND in node) ? node[_BOND][key] : void 0;
}

// uuMeta.bond.keys - find node bonded keywords
function keys(node) { // @param Node:
                      // @return StringArray: ["key", ...]
  var uid = _mm.uid(node), key, rv = [];

  if (uid in _uiddb) {
    for (key in _keydb) {
      if (uid in key) {
        rv.push(key);
      }
    }
  }
  return rv;
}

// uuMeta.bond.nodes - find keyword bonded nodes
function nodes(key) { // @param String: keyword
                      // @return NodeArray: [node, ...]
  var uid, rv = [];

  if (key in _keydb) {
    for (uid in _keydb[key]) {
      rv.push(_uiddb[uid]);
    }
  }
  return rv;
}

// --- initialize ---

// --- export ---
_mm.bond    = bond;   // uuMeta.bond
_mm.unbond  = unbond; // uuMeta.unbond
bond.get    = get;    // uuMeta.bond.get
bond.keys   = keys;   // uuMeta.bond.keys
bond.nodes  = nodes;  // uuMeta.bond.nodes

})(); // uuMeta.bond scope

